import fs from "fs"
import yaml from "js-yaml"
import fetch from "node-fetch"

export class api extends plugin {
  constructor() {
    super({
      name: "GT插件",
      event: "message",
      priority: 33700,
      rule: [
        {
          reg: "^#*[Gg][Tt]使用接口\\d+$",
          fnc: "change"
        },
        {
          reg: "^#*[Gg][Tt]信息$",
          fnc: "info"
        },
        {
          reg: "^#*[Gg][Tt]接口(列表|)$",
          fnc: "list"
        }
      ]
    })

    this.configPath = "./plugins/GT-Manual-Plugin/config/"
    this.configDef = "./plugins/GT-Manual-Plugin/def/"
  }

  async list(e) {
    if (!e.isMaster) return false

    let api_list = this.list_api()
    let msg = ["-------GT接口列表-------"]
    let num = 1

    if (api_list.length <= 0) return await e.reply("暂无接口")
    else await e.reply("检测可用性中，请稍后。。。")

    for (let i of api_list) {
      let res = await this.checkLink(i.verifyAddr)
      msg.push(`${num}.${i?.name || i.verifyAddr}：${res ? res : "否"}`)
      num++
    }
    if (msg.length <= 0) await e.reply("接口测试失败")
    else await e.reply(msg.join("\n\n"))
  }

  async info(e) {
    if (!e.isMaster) return false

    let api_list = this.list_api()
    let config = yaml.load(fs.readFileSync(this.configPath + "gt.yaml", "utf8"))
    let name = 1

    for (let i of api_list) {
      if (i.verifyAddr === config.verifyAddr) {
        if (i?.name) {
          name = i.name
        }
        break
      }
      name += 1;
    }

    let verify = {
      0: "关闭",
      1: "开启",
      2: "仅原神",
      3: "仅星铁"
    }
    let msg = [
      "-------GT信息-------",
      `手动验证：${verify[config.verify]}`,
      `验证接口：${name}`
    ]
    if (e?.friend) {
      msg.push("验证链接：")
      if (config.name) msg.push(`  - ${config.name}`)
      msg.push(`  - ${config.verifyAddr}`)
      msg.push(`  - ${config.signAddr || "未知"}`)
    }
    let res = await this.checkLink(config.verifyAddr)
    msg.push(`接口是否可用：${res ? res : "否"}`)
    msg.push(`手动签到：${config.sign ? "开启" : "关闭"}`)
    if (e?.friend && Array.isArray(config.blackList) && config.blackList.length) {
      msg.push("黑名单QQ")
      config.blackList.map(i => msg.push(`  - ${i}`))
    }
    await e.reply(msg.join("\n\n"))
  }

  async change(e) {
    if (!e.isMaster) return false

    let api_list = this.list_api()
    let index = Number(e.msg.replace(/^#*[Gg][Tt]使用接口/, "").trim()) - 1

    if (!api_list?.[index]?.verifyAddr) return await e.reply("接口不存在", true)
    if (!api_list?.[index]?.signAddr) e.reply("签到地址不存在将无法进行签到")
    let config = yaml.load(fs.readFileSync(this.configPath + "gt.yaml", "utf8"))

    if (api_list[index]?.name) config.name = api_list[index].name
    config.verifyAddr = api_list[index].verifyAddr
    config.signAddr = api_list[index].signAddr
    fs.writeFileSync(this.configPath + "gt.yaml", yaml.dump(config))
    let msg = [`已将GT接口替换为接口[${api_list[index]?.name || index + 1}]`]
    let res = await this.checkLink(config.verifyAddr)
    if (res && res !== "超时") {
      msg.push(`接口速度：${res}`)
      msg.push(`请重启云崽后生效`)
    } else {
      msg.push(`接口${res ? res : "无法访问"}，请切换其他接口`)
    }
    await e.reply(msg.join("\n"), true)
  }

  async checkLink(url, timeoutTime = 5) {
    const AbortController = globalThis.AbortController || await import("abort-controller")

    const controller = new AbortController()
    const timeout = setTimeout(() => {
      controller.abort()
    }, timeoutTime * 1000)

    try {
      let start = Date.now()
      const res = await fetch(url, { signal: controller.signal })
      if (res.ok) {
        return `${Date.now() - start}ms`
      } else {
        logger.warn(`[GT接口][${url}] ${res.status} ${res.statusText}`)
        return res.status
      }
    } catch (error) {
      logger.warn("[GT接口][检查链接是否可访问]", error)
      if (error.name === "AbortError") {
        return "超时"
      } else {
        return false
      }
    }
  }

  list_api() {
    // 合并配置文件
    let defset = yaml.load(fs.readFileSync(this.configDef + "api.yaml", "utf8"))
    let userset = yaml.load(fs.readFileSync(this.configPath + "api.yaml", "utf8"))
    let api_list = [...defset, ...userset]
    api_list = [...new Set(api_list.map(JSON.stringify))].map(JSON.parse)
    return api_list
  }
}
